package com.jic.data.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * @author wj
 * @date: 2020年02月14日
 */
@Aspect
@Component
@Slf4j
public class VisitLogIntercept {

    ThreadLocal<Long> startTime = new ThreadLocal<Long>();

    //申明一个切点 里面是 execution表达式
    @Pointcut("execution(public * com.jic.data.controller.*..*.*(..))")
    private void controllerAspect() {
    }


    //请求method前打印内容
    @Before(value = "controllerAspect()")
    public void methodBefore(JoinPoint joinPoint) {
        startTime.set(System.currentTimeMillis());

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        //打印请求内容
        log.info("===============请求内容===============");
        log.info("请求地址:{}", request.getRequestURL().toString());
        log.info("请求方式:{}", request.getMethod());
        log.info("请求类方法:{}", joinPoint.getSignature());
        log.info("请求类方法参数:{}", Arrays.toString(joinPoint.getArgs()));
        log.info("===============请求内容===============");
    }

    //环绕执行
    //定义需要匹配的切点表达式，同时需要匹配参数
    @Around(value = "controllerAspect()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        log.info("==================方法环绕前置start=====================>");
        //这句必须有 往下执行方法
        Object result = pjp.proceed();

        log.info("==================方法环绕后置start=====================>");
        log.info("耗时（毫秒）：{}", (System.currentTimeMillis() - startTime.get()));
        log.info("返回数据：{}", result);
        log.info("==================方法环绕end======================>");
        return result;
    }

    //在方法执行完结后打印返回内容
    @AfterReturning(returning = "o", pointcut = "controllerAspect()")
    public void methodAfterReturing(Object o) {
        log.info("--------------返回内容----------------");
        log.info("Response内容:" + JSON.toJSONString(o));
        log.info("--------------返回内容----------------");

        log.info("请求消耗时间：{}ms", (System.currentTimeMillis() - startTime.get()));

    }

}
